gabcSettings.trimStaff=false;
gabcSettings.showSyllableEditorOnHover=false;
var gabcheader=null,
    selHeight=11,selWidth=4.5,selSpacing='vichi',selLayout='satb',selKey='c',selTransposeKey='c',selTransposeNum=0,selTransposeUpDown=false,selTemplate='antiphon',
    selSharpsFlats=false,
    overrideSpacing=false,
    overrideHeight=false,
    overrideWidth=false,
    engravingType='square',
    selRefrainTop=false;
function updateBoth(e){
  var $editor = $("#editor");
  var gabc = $editor.val();
  var $cbHideTextLeft = $('#cbHideTextLeft');
  gabcheader=getHeader(gabc);
  var val;
  var selStart = $editor[0].selectionStart;
  if(selStart >= gabcheader.original.length) {
    var selEnd = $editor[0].selectionEnd;
    if(!gabcheader.cValues.width) gabcheader.cValues.width = selWidth;
    if(!gabcheader.cValues.height) gabcheader.cValues.height = selHeight;
    if(typeof(gabcheader.cValues.spacing)!='string') gabcheader.cValues.spacing = selSpacing;
    var oLen = gabcheader.original.length;
    var header = gabcheader.toString();
    var nLen = header.length;
    var scrollTop = $editor.scrollTop();
    $editor.val(header + gabc.slice(oLen));
    $editor.scrollTop(scrollTop);
    if(oLen != nLen) {
      $editor[0].selectionStart = selStart -oLen +nLen;
      $editor[0].selectionEnd = selEnd -oLen +nLen;
    }
  } 
  var hideTextLeft = (gabcheader.cValues['hide-text-left'] && gabcheader.cValues['hide-text-left'] != 'false')? true : false;
  if(hideTextLeft != $cbHideTextLeft.prop('checked')) {
    $cbHideTextLeft.prop('checked',hideTextLeft).change();
  }
  if(gabcheader.cValues.width != selWidth) {
    val = parseFloat(gabcheader.cValues.width);
    switch(val){
      case 4:
        $("#rbWidth4")[0].checked = true;
        $("#rbWidth4").button("refresh");
        selWidth = val;
        break;
      case 5:
        $("#rbWidth5")[0].checked = true;
        $("#rbWidth5").button("refresh");
        selWidth = val;
        break;
      case 4.5:
        $("#rbWidth45")[0].checked = true;
        $("#rbWidth45").button("refresh");
        selWidth = val;
        break;
      default:
        if(val) {
          $("#rbWidthCustom")[0].checked = true;
          $("#rbWidthCustom").button("refresh");
          selWidth = val;
          $("#txtWidth").val(selWidth);
        }
        break;
    }
    widthChanged(selWidth);
  }
  if(gabcheader.cValues.height != selHeight) {
    val = parseFloat(gabcheader.cValues.height);
    switch(val){
      case 9:
        $("#rbHeight9")[0].checked = true;
        $("#rbHeight9").button("refresh");
        selHeight = val;
        break;
      case 11:
        $("#rbHeight11")[0].checked = true;
        $("#rbHeight11").button("refresh");
        selHeight = val;
        break;
      default:
        if(val){
          $("#rbHeightCustom")[0].checked = true;
          $("#rbHeightCustom").button("refresh");
          selHeight = val;
          $("#txtHeight").val(selHeight);
        }
    }
    heightChanged(selHeight);
  }
  if(typeof(gabcheader.cValues.spacing)=='string' && gabcheader.cValues.spacing != selSpacing) {
    selSpacing = gabcheader.cValues.spacing;
    switch(selSpacing){
      case "vichi":
        $("#rbSpacingVichi")[0].checked = true;
        $("#rbSpacingVichi").button("refresh");
        break;
      case "smith":
        $("#rbSpacingSmith")[0].checked = true;
        $("#rbSpacingSmith").button("refresh");
        break;
      default:
        $("#rbSpacingDefault")[0].checked = true;
        $("#rbSpacingDefault").button("refresh");
        selSpacing = "";
        break;
    }
    spacingChanged(selSpacing);
  }
  updateLocalHeader(gabcheader);
}

function dimensionsFromLy(ly) {
  var height = /paper-height\s+=\s+(\d*(?:\.\d+)?)\\in/.exec(ly);
  var width = /paper-width\s+=\s+(\d*(?:\.\d+)?)\\in/.exec(ly);
  height = height? parseFloat(height[1]) : selHeight;
  width = width? parseFloat(width[1]) : selWidth;
  return {w:width, h:height};
}

function setPaperFromLy(ly){
  var dim = dimensionsFromLy(ly);
  selHeight = dim.h
  selWidth = dim.w;
  widthChanged(selWidth);
  heightChanged(selHeight);
}

function updateLocalHeader(header) {
  localStorage.transcribeHeader=header;
}
function callLyPdf(e){
  filename = $('#lyName').val() || "Untitled";
  //$("._filename").val(filename);
  $("._name").val(filename);
  $("._dir").val($('#lyDir').val());
  $('._sop').val($('#lySop').val());
  $('._alt').val($('#lyAlt').val());
  $('._ten').val($('#lyTen').val());
  $('._bas').val($('#lyBas').val());
  $('._lyrics').val($('#lyLyrics').val());
  $('._chords').val($('#lyChords').val());
  $('._refrain').val($('#lyRefrain').val());
  $('._refrainAtBeginning').val(selRefrainTop?'1':'');
  $('._commentary').val($('#lyCommentary').val());
  $('._userNotes').val($('#lyUserNotes').val());
  $('._annotation').val($('#lyAnnotation').val());
  $('._modeoffset').val($('#lyModeOffset').val());
  $('._raggedlast').val($('#lyRaggedLast').prop('checked')?'t':'');
  $('._verseOneName').val($('#lyVerseOneName').val());
  $('._verseOne').val($('#lyVerseOne').val());
  $('._verseTwoName').val($('#lyVerseTwoName').val());
  $('._verseTwo').val($('#lyVerseTwo').val());
  $('._verseThreeName').val($('#lyVerseThreeName').val());
  $('._verseThree').val($('#lyVerseThree').val());
  $('._verseFourName').val($('#lyVerseFourName').val());
  $('._verseFour').val($('#lyVerseFour').val());
  $('._verseFiveName').val($('#lyVerseFiveName').val());
  $('._verseFive').val($('#lyVerseFive').val());
  $('._verseSixName').val($('#lyVerseSixName').val());
  $('._verseSix').val($('#lyVerseSix').val());
  $('._tune').val($('#lyTune').val());
  $('._text').val($('#lyText').val());
  $('._meter').val($('#lyMeter').val());
  $('._author').val($('#lyAuthor').val());
  $('._copyright').val($('#lyCopyright').val());
  $('._suppressTimeSignature').val($('#lySuppressTimeSignature').is(':checked')?'1':'');
  $('._suppressStems').val($('#lySuppressStems').is(':checked')?'1':'');
  $('._harmonization').val($('#lyHarmonization').val());
  $('._ignoreDurations').val($('#lyIgnoreDurations').is(':checked')?'1':'');
  $('._separateVoices').val($('#lySeparateVoices').is(':checked')?'1':'');
  $('._solidifyDashedSlurs').val($('#lySolidifyDashedSlurs').is(':checked')?'1':'');
  $('._hideDashedSlurs').val($('#lyHideDashedSlurs').is(':checked')?'1':'');
  $('._useTuneInFileName').val($('#lyUseTuneInFileName').is(':checked')?'1':'');
  
  $('#lyForm').submit();
}
function callPdf(e){
  if(e && typeof(e.preventDefault)=="function"){
    e.preventDefault();
  }
  if(engravingType == 'modern') {
    callLyPdf(e);
  } else {
    var src = splitGabc($("#editor").val())[0];
    $("._name").val(gabcheader.name || "Untitled");
    $("#pdff_src").val(src);
    $("#pdfForm").submit();
  }
}

function callImage(e){
  $("#imgf_type").val(engravingType);
  var src = splitGabc($("#editor").val())[0];
  var filename;
  if(engravingType=='square'){
    filename = gabcheader.name || "Untitled";
  } else {
    filename = getLyFilename(src) || "Untitled";
    $("#imgf_dir").val(getLyDir(src));
  }
  if(e && typeof(e.preventDefault)=="function"){
    e.preventDefault();
  }
  $("#imgf_filename").val(filename);
  $("#imgf_src").val(src);
  $("#imageForm").submit();
}

function callSave(e){
  if(e && typeof(e.preventDefault)=="function"){
    e.preventDefault();
  }
  processGabc($("#editor").val());
}

function updateLocalHeader(header) {
  localStorage.transcribeHeader=header;
}

function updateEditorHeader(newHeader){
  var wholeText = $("#editor").val();
  var oldHeader = getHeader(wholeText);
  var newText = newHeader + wholeText.slice(oldHeader.original.length);
  $("#editor").val(newText);
}

function splitGabc(gabc){
  var result=[];
  var lines=gabc.split(/\r?\n/);
  var state=0;
  var current='';
  lines.forEach(function(line){
    switch(state){
      case 0:
        if(line.match(/^%%$/))state=1;
        break;
      case 1:
        if(line.match(/^\s*[-\w]+:[^;]+;\s*$/)){
          state=0;
          result.push(current);
          current='';
        }
        break;
    }
    current += line + '\n';
  });
  if(current.length)result.push(current);
  return result;
}
var gabcQueue = [];
var gabcProcessing = [];
var maxConcurrent = 5;
var processUrl = "../process.php"
function GabcJob(src){
  this.src = src;
  this.header = getHeader(src);
  if(engravingType=='modern'){
    this.type = 'modern';
    this.filename=$('#lyName').val()||"Untitled";
    this.dir=getLyDir(src);
    this.vars = {
      type: this.type,
      name: this.filename,
      dir: this.dir,
      key: $('#ly_key').val(),
      sop: $('#lySop').val(),
      alt: $('#lyAlt').val(),
      ten: $('#lyTen').val(),
      bas: $('#lyBas').val(),
      lyrics: $('#lyLyrics').val(),
      chords: $('#lyChords').val(),
      refrain: $('#lyRefrain').val(),
      refrainAtBeginning: $('#ly_refrainAtBeginning').val(),
      commentary: $('#lyCommentary').val(),
      userNotes: $('#lyUserNotes').val(),
      annotation: $('#lyAnnotation').val(),
      modeoffset: $('#lyModeOffset').val(),
      raggedlast: $('#lyRaggedLast').prop('checked')?'t':'',
      verseOneName: $('#lyVerseOneName').val(),
      verseOne: $('#lyVerseOne').val(),
      verseTwoName: $('#lyVerseTwoName').val(),
      verseTwo: $('#lyVerseTwo').val(),
      verseThreeName: $('#lyVerseThreeName').val(),
      verseThree: $('#lyVerseThree').val(),
      verseFourName: $('#lyVerseFourName').val(),
      verseFour: $('#lyVerseFour').val(),
      verseFiveName: $('#lyVerseFiveName').val(),
      verseFive: $('#lyVerseFive').val(),
      verseSixName: $('#lyVerseSixName').val(),
      verseSix: $('#lyVerseSix').val(),
      template: $('#ly_template').val(),
      layout: $('#ly_layout').val(),
      key: $('#ly_key').val(),
      transposekey: $('#ly_transposekey').val(),
      tune: $('#lyTune').val(),
      text: $('#lyText').val(),
      meter: $('#lyMeter').val(),
      author: $('#lyAuthor').val(),
      copyright: $('#lyCopyright').val(),
      suppressTimeSignature: $('#lySuppressTimeSignature').is(':checked')?'1':'',
      suppressStems: $('#lySuppressStems').is(':checked')?'1':'',
      useTuneInFileName: $('#lyUseTuneInFileName').is(':checked')?'1':'',
      harmonization: $('#lyHarmonization').val(),
      ignoreDurations: $('#lyIgnoreDurations').is(':checked')?'1':'',
      separateVoices: $('#lySeparateVoices').is(':checked')?'1':'',
      solidifyDashedSlurs: $('#lySolidifyDashedSlurs').is(':checked')?'1':'',
      hideDashedSlurs: $('#lyHideDashedSlurs').is(':checked')?'1':'',
      width: selWidth,
      height: selHeight,
      croppdf: $("#cbCrop")[0].checked,
      save:true
    };
  } else {
    this.type = 'square';
    this.filename=(this.header && this.header.name)||"Untitled";
    this.vars = {
      src:this.src,
      type:this.type,
      filename:this.filename,
      croppdf:$("#cbCrop")[0].checked,
      width:this.header.cValues.width || selWidth,
      height:this.header.cValues.height || selHeight,
      spacing:typeof(this.header.cValues.spacing)=='string'? this.header.cValues.spacing : selSpacing,
      save:true
    };
  }
  
  var notification = this.notification = $("<div>Queued "+this.filename+"...</div>");
  this.fadeNotification=function(){
    notification.fadeOut();
  };
}

GabcJob.prototype.queue = function(){
  $("#notifications").append(this.notification);
  if(gabcProcessing.length < maxConcurrent) {
    this.run();
  } else {
    gabcQueue.push(this);
  }
};
GabcJob.prototype.run = function(){
  gabcProcessing.push(this);
  this.notification.text('Processing '+this.filename+'...');
  $.post(processUrl,this.vars)
    .complete(this.postCompleted).gabcJob = this;
};
GabcJob.prototype.postCompleted = function(e,result){
  var i;
  var job = e.gabcJob;
  while((i = gabcProcessing.indexOf(job)) >= 0){
    gabcProcessing.splice(i,1);
  }
  var nextGabc = gabcQueue.shift();
  if(nextGabc)nextGabc.run();
  if(result=="success"){
    if(e.getResponseHeader("Content-Type")=="text/plain"){
      job.notification.append("<span style='color:red;font-weight:700'>ERROR:</span><blockquote>"+e.responseText+"</blockquote>");
    } else {
      job.notification.append("done!");
      setTimeout(job.fadeNotification,1000);
      return;
    }
  } else {
    job.notification.append("<span style='color:red;font-weight:700'>"+result+":</span><blockquote>"+e.responseText+"</blockquote>");
  }
  job.notification.click(job.fadeNotification);
};

function processGabc(src){
  if(engravingType=='modern'){
    new GabcJob("").queue();
  } else {
    splitGabc(src.replace(/\u2028/g,'')).forEach(function(src){
      new GabcJob(processDraggedFile(src)).queue();
    });
  }
}

function getLyDir(ly){
  return $('#lyDir').val()||'sandbox';
}
function getLyFilename(ly){
  return getFilenameForTitle(getLyTitle(ly));
}
function getFilenameForTitle(title){
  return title.toLowerCase().replace(/\W+/g,'-');
}
function getLyTitle(ly){
  var regexTitle = /title\s*=[^"\(]*(?:\([^\)]*\))?[^"]*"([^"]*)"/;
  //var regexTitle = /title\s*=\s*"([^"]*)"/;
  var match = regexTitle.exec(ly);
  if(match) return match[1]
  else return "Untitled";
}

function docKeyDown(e){
  if($("#overlay").css("display")!="none"){
    e.preventDefault();
    hideImage();
  }
  if(e.ctrlKey) {
    if(e.which==69) {//E
      toggleEditorVisiblity();
      e.preventDefault();
    } else if(e.which==83) {//S
      //save
      e.preventDefault();
      callSave();
    } else if(e.which==80){//P
      //Preview
      e.preventDefault();
      if(e.shiftKey){
        callPdf();
      } else {
        callImage();
      }      
    }
  }
}

function widthChanged(width,forceUpdateGabc){
  var val = typeof(width)=="number"? width :
    $("#rbWidth4")[0].checked? 4 :
    $("#rbWidth5")[0].checked? 5 :
    $("#rbWidth45")[0].checked? 4.5 :
    parseFloat($("#txtWidth").val()) || 5;
  selWidth= val;
  gabcheader = gabcheader || getHeader($("#editor").val());
  if(gabcheader.cValues.width != val && (forceUpdateGabc || width!=selWidth)) {
    gabcheader.cValues.width = val;
    updateEditorHeader(gabcheader);
  }
  setWidthLabel();
  $("._width").val(val);
}
function setWidthLabel(){
  $("#btnWidth").button("option","label","Width: " + (overrideWidth?'<b>':'') + selWidth + "in" + (overrideWidth?'</b>':''));
}

function heightChanged(height,forceUpdateGabc){
  var val = typeof(height)=="number"?height :
    $("#rbHeight9")[0].checked? 9 :
    $("#rbHeight11")[0].checked? 11 :
    parseFloat($("#txtHeight").val()) || 11;
  selHeight=val;
  gabcheader = gabcheader || getHeader($("#editor").val());
  if(gabcheader.cValues.height != val && (forceUpdateGabc || height!=selHeight)){
    gabcheader.cValues.height = val;
    updateEditorHeader(gabcheader);
  }
  setHeightLabel();
  $("._height").val(val);
}

function setHeightLabel(){
  $("#btnHeight").button("option","label","Height: " + (overrideHeight?'<b>':'') + selHeight + "in" + (overrideHeight?'</b>':''));
}

function layoutChanged(layout){
  if(typeof(layout)=='string') {
    $('input[name=rbLayout][value='+layout+']').prop('checked',true).change();
    return;
  }
  var val = typeof(layout)=='string'?layout : $("input[name=rbLayout]:checked").val();
  $('#lblSop').text((val=='melody')? 'Melody' : 'Soprano');
  selLayout=val;
  setLayoutLabel();
  $('div.SATB').toggle(selLayout=='satb' && selTemplate != 'hymn');
  $("._layout").val(val);
  setLyTuneAutocomplete();
  windowResized();
}

function setLayoutLabel(){
  var cb = $("input[type=radio][value=" + selLayout + "]")[0];
  $("#btnLayout").button("option","label",$("label[for="+cb.id+"]").text());
}

function cropChanged(){
  var checked=this.checked;
  $("._croppdf").val(checked);
  $(this).button({icons:checked?{primary: "ui-icon-check"}:{}});
}

function hideTextLeftChanged(e){
  console.info(e);
  var checked=this.checked;
  $(this).button({icons:checked?{primary: "ui-icon-check"}:{}});
  if(e.originalEvent) {
    setGabcForHideTextLeft(this.checked);
  }
}

function setGabcForHideTextLeft(checked){
  var $editor = $('#editor');
  var editorVal = $editor.val();
  var header = getHeader(editorVal);
  if(checked) {
    header.cValues['hide-text-left'] = 'true';
  } else {
    header.cValues['hide-text-left'] = 'false';
  }
  editorVal = header.toString() + editorVal.slice(header.original.length);
  $editor.val(editorVal);
}

function templateChanged(template){
  if(typeof(template)=='string') {
    if(template=='psalm-tone') template = 'choral-tone';
    $('input[name=rbTemplate][value='+template+']').prop('checked',true).change();
  } else {
    template = $("input[name=rbTemplate]:checked").val();
  }
  var val = template;
  if(selTemplate=='harmonization' && val=='hymntune') {
    var tune = $('#lyTune').val();
    $('#lyName').val(tune.replace(/-/g,' ').replace(/\.json$/,'')).change();
  } else if(selTemplate=='hymntune' && val=='harmonization') {
    var name = $('#lyName').val();
    $('#lyName').val('default');
    $('#lyTune').val(name.replace(/\s+/g,'-') + '.json').change();
  }
  selTemplate=val;
  $('.lyTemplate').hide(0);
  $('.' + selTemplate).show(0);
  setTemplateLabel();
  $('div.SATB').toggle(selLayout=='satb' && selTemplate != 'hymn');
  $("._template").val(val);
  setLyTuneAutocomplete();
  windowResized();
}

function setTemplateLabel(){
  var cb = $("input[type=radio][value=" + selTemplate + "]")[0];
  $("#btnTemplate").button("option","label",$("label[for="+cb.id+"]").text());
}

function typeChanged(type){
  if(typeof(type)=='string') {
    $('input[name=rbType][value='+type+']').prop('checked',true).change();
  } else {
    type = $("input[name=rbType]:checked").val();
  }
  engravingType=type;
  var extension;
  if(engravingType=='square'){
    engravingType='square';
    extension='gabc';
    dontUpdateChant=false;
    $('.lyOnly').hide(0);
    $('.gabcOnly').show(0);
  } else {
    dontUpdateChant=true;
    engravingType='modern';
    extension='json';
    $('.gabcOnly').hide(0);
    $('.lyOnly').show(0);
    templateChanged();
  }
  $('#txtLoad').autocomplete({
    source: "../ac.php?root=engravings/"+engravingType+"/&extension="+extension,
    select: loadSelect,
    minLength: 0
  });
  setTypeLabel();
  $("._type").val(type);
  windowResized();
}

function setTypeLabel(){
  var cb = $("input[type=radio][value=" + engravingType + "]")[0];
  $("#btnType").button("option","label",$("label[for="+cb.id+"]").text());
}

function spacingChanged(spacing,forceUpdateGabc){
  var cb = this;
  if(this.id && $("label[for="+this.id+"]").length){
    cb = this;
  } else {
    cb = $("input[type=radio][value=" + spacing + "]")[0];
    if(!cb)return;
    cb.checked = true;
  }
  if(cb.checked)selSpacing = cb.value;
  if(cb.checked){
    var val=selSpacing;
    gabcheader = gabcheader || getHeader($("#editor").val());
    if(gabcheader.cValues.spacing != val && (forceUpdateGabc || spacing!=selSpacing)){
      gabcheader.cValues.spacing = val;
      updateEditorHeader(gabcheader);
    }
    setSpacingLabel();
    $("._spacing").val(val);
  }
}

function setSpacingLabel(){
  var cb = $("input[type=radio][value=" + selSpacing + "]")[0];
  $("#btnSpacing").button("option","label","Spacing: " + (overrideSpacing?'<b>':'') + $("label[for="+cb.id+"]").text() + (overrideSpacing?'</b>':''));
}

function hideImage(){
  $("#overlay,#chant-image").hide();
}

function lightboxImage(){
  $ci=$("#chant-image-iframe");
  $i=$("img",$ci[0].contentDocument);
  $($ci[0].contentDocument&&$ci[0].contentDocument.body).css("margin","2px");
  $($ci[0].contentDocument).click(hideImage);
  var width="7in";
  var height="70%";
  if($ci[0].contentDocument && $i[0]){
    width=$i[0].width+4;
    height=$i[0].height+4;
  }
  //$ci.css("width","10000").css("height","10000");
  $ci.css("height",height)
    .css("width",width)
    .css("margin-top",Math.min($ci.parent().height(),$ci.height())*(-0.33))
    .css("margin-left",Math.min($ci.parent().width(),$ci.width())/(-2));
  $("#chant-image,#overlay").show();
}

var dontHide=[];
function showRadio(){
  positionRadio(this);
  var id=this.id.replace(/^lbl/,'#radio');
  $(id).fadeIn(200);
  if(dontHide.indexOf(id)==-1)dontHide.push(id);
}
function hideRadio(){
  var id=this.id.replace(/^lbl/,'#radio');
  delete dontHide[dontHide.indexOf(id)];
  setTimeout(function(){
    if(dontHide.indexOf(id)==-1)$(id).fadeOut(200);
  }, 100);
}
function dontAllowHide(){
  var id="#"+this.id;
  if(dontHide.indexOf(id)==-1)dontHide.push(id);
}
function allowHide(){
  var id="#"+this.id;
  delete dontHide[dontHide.indexOf(id)];
  setTimeout(function(){
    if(dontHide.indexOf(id)==-1)$(id).fadeOut(200);
  }, 100);
}

function positionRadio(e){
  var id=e.id.match(/^(?:radio|btn|lbl)(.*)$/);
  if(!id)return;
  id=id[1];
  var display=$("#radio"+id).css("display");
  $("#radio"+id).show().position({my:"center-2 top-4",at:"bottom",of:$("#lbl"+id),collision:"fit"}).css("display",display);
}

function windowResized(){
  var $cp = $("#chant-parent2"),
      $ed = $("#editor"),
      edHeight = $ed.is(':visible')? $ed.height() : 0,
      totalHeight = $(window).height() - $cp.position().top - 18 + edHeight;
  if(edHeight) {
    edHeight = Math.max(104,totalHeight*0.4);
    $ed.height(edHeight);
  }
  $cp.height(totalHeight - edHeight);
  $('#txtLoad,#txtLoadText,#lyName,#lyDir,#lyText,#lyTune,#lyMeter,#lyAuthor,#lyCopyright,#lyHarmonization,#lyAnnotation,#lyModeOffset,#lyUserNotes,#lyCommentary').each(function(){
    var $this = $(this);
    var discrepancy = $this.outerWidth(false) - $this.width() + 1;
    $this.width($this.parent().width() - $($this.prop('labels')).width() - discrepancy);
  });
}
function overrideChanged(e){
  var override = this.checked;
  switch (this.id) {
    case 'btnSpacing':
      overrideSpacing = override;
      setSpacingLabel();
      break;
    case 'btnHeight':
      overrideHeight = override;
      setHeightLabel();
      break;
    case 'btnWidth':
      overrideWidth = override;
      setWidthLabel();
      break;
    case 'btnType':
    case 'btnTemplate':
    case 'btnLayout':
      var name = this.id.slice(3);
      this.checked = false;
      $(this).button('refresh');
      var $radios = $('input[name=rb'+name+']');
      var next = false;
      $radios.each(function(){
        if(next) {
          next = $(this);
          return false;
        }
        if($(this).is(':checked')) {
          next = true;
        }
      });
      if(!next || next === true) {
        next = $radios.first();
      }
      next.prop('checked',true);
      next.change();
      windowResized();
      break;
  }
}
var processDraggedFile = function(txt){
  var gabcheader = getHeader(txt);
  if(overrideWidth || !gabcheader.cValues.width) gabcheader.cValues.width = selWidth;
  if(overrideHeight || !gabcheader.cValues.height) gabcheader.cValues.height = selHeight;
  if(overrideSpacing || typeof(gabcheader.cValues.spacing)!='string') gabcheader.cValues.spacing = selSpacing;
  txt = gabcheader + txt.slice(gabcheader.original.length);
  return txt;
};
function loadSelectText(e,ui){
  if(ui.item.value.slice(-1)=='/') {
    $(this).autocomplete('search',ui.item.value);
  } else {
    loadText(ui.item.value);
  }
}
function loadSelect(e,ui){
  if(ui.item.value.slice(-1)=='/') {
    $(this).autocomplete('search',ui.item.value);
  } else {
    load(ui.item.value);
  }
}
function loadText(load){
  if(load){
    $.get('../get.php?file=texts/'+load,function(data){
      var options, $txt, header;
      if(data.slice(0,2).match(/^[A-Z]+$/)) {
        data = data[0] + data.slice(1,3).toLowerCase() + data.slice(3);
      }
      switch(engravingType) {
        case 'square':
          options = Dic.gregorio;
          $txt = $('#editor');
          header = getHeader($txt.val()) + '(c4)';
          break;
        default:
          options = Dic.lilypond;
          $txt = $('#lyLyrics');
          header = '';
          break;
      }
      data = data.replace(/\b\+\b/g,options.delimiter);
      var text = Dic.syllabify(data, options, function(){
        $txt.val(header+Dic.syllabify(data, options)).trigger('autosize.resize');
      });
      $txt.val(header+text).trigger('autosize.resize');
    });
  }
}
function load(load){
  if(load){
    $.get('../get.php?file=engravings/'+engravingType+'/'+load,function(data){
      location.hash='#'+engravingType+'/'+load;
      if(load.slice(-5)=='.gabc') {
        typeChanged('square');
        $('#txtLoad').val(load);
        $('#editor').val(data).keyup();
        var hideTextLeft = gabcheader.cValues['hide-text-left']!='false';
        $('#cbHideTextLeft').prop('checked',hideTextLeft).change();
        setGabcForHideTextLeft(hideTextLeft);
      } else if(typeof(data)=='object') {
        clearFields();
        typeChanged('modern');
        templateChanged(data['template']);
        layoutChanged(data['layout']);
        for(key in data){
          var $obj = $('[name=' + key + ']');
          if($obj.is(':radio,:checkbox')) {
            $obj.prop('checked',data[key]?true:false);
          } else {
            $obj.val(data[key]);
          }
          $obj.change();
          if(key == 'refrainAtBeginning') {
            if(data[key]? !selRefrainTop : selRefrainTop) {
              $('#toggleRefrainPosition').click();
            }
          }
        }
        $('textarea.autosize').trigger('autosize.resize');
        $('#cbCrop').prop('checked',data['croppdf']!='false').change();
        widthChanged(data['width']);
        heightChanged(data['height']);
        selKey = data['key'];
        $('._key').val(selKey);
        setKey(selKey);
        selTransposeKey = data['transposekey'] || selKey;
        $('._transposekey').val(selTransposeKey)
        setTransposeKey(selTransposeKey);
      }
    });
  }
}
function setInitialCaps(e){
  e.preventDefault();
  var $editor = $('#editor'),
      text = $editor.val(),
      headerLen = getHeaderLen(text),
      realText = text.slice(headerLen),
      m = realText.match(/^(?:\s+|\([^)]*\))+/),
      result;
  if(m) {
    headerLen += m[0].length;
    realText = text.slice(headerLen);
  }
  m = realText.match(/^[a-z]+/i);
      
  if(m) {
    m = m[0];
    result = m[0].toUpperCase();
    if(m[1]) {
      result += m[1].toUpperCase();
      if(m[2] && m.length==3 && (realText[3]=='(' || realText[3]==',')) {
        result += m[2].toUpperCase();
      }
    }
    $editor.val(text.slice(0,headerLen) + result + text.slice(headerLen + result.length));
  }
}
function removeClick(e){
  e.preventDefault();
  var remove = $(this).attr('remove');
  var outsideParentheses = $(this).attr('outsideParentheses');
  var $editor = $('#editor');
  var text = $editor.val();
  var headerLen = getHeaderLen(text);
  var head = text.slice(0,headerLen);
  var text = text.slice(headerLen);
  var regexBase = outsideParentheses? '((?:$|\\))[^(]*)' : '(\\([^)]*)';
  var regex = new RegExp(regexBase+remove,'g');
  var newText;
  while(text != (newText = text.replace(regex,'$1'))) {
    text = newText;
  }
  $editor.val(head + text).keyup();
}
function clearFields(e){
  $('.clearableField').val('').prop('checked',false).change();
  $('#editor').val('user-notes:;\ncommentary:;\nannotation:;\ncentering-scheme:english;\n%%\n(c4)').keyup();
  
  if(e && typeof(e.preventDefault)=='function') {
    $('.-clearableField').val('');
    e.preventDefault();
  }
}
var updateTransposeUpDownText = function(){
  var str = selTransposeUpDown?'+':'-';
  $('#btnTransposeUpDown').text(str);
  selTransposeNum = (selTransposeUpDown? 1 : -1) * $('#txtTranspose').val();
  updateTransposeKey();
};
function txtTransposeKeyDown(e){
  switch(e.which) {
    case 189: // minus
    case 109: // numpad minus
      selTransposeUpDown = false;
      e.preventDefault();
      break;
    case 187: // equals/plus
    case 107: // numpad plus
      selTransposeUpDown = true;
      e.preventDefault();
      break;
  }
  updateTransposeUpDownText();
}
function txtTransposeKeyUp(e){
  updateTransposeUpDownText();
}
function txtKeyUp(e){
  updateSharpsFlatsText();
  this.selectionStart = 0;
  this.selectionEnd = 1;
  var val = this.value;
}
var updateSharpsFlatsText = function(){
  var str = selSharpsFlats?'Sharps':'Flats';
  if($('#txtKeyNum').val()=='1') {
    str = str.slice(0,-1);
  }
  $('#btnSharpsFlats').text(str);
  updateKeySig();
};
var setTransposeKey = function(transposeKey){
  var keyNum = keyToNum(transposeKey);
  var diff = keyNum - keyToNum(selKey);
  selTransposeNum = diff;
  $('#txtTranspose').val(Math.abs(diff));
  selTransposeUpDown = (diff >= 0);
  updateTransposeUpDownText();
};
var setKey = function(key){
  var regex = /^([a-gA-G])([ei]s)?$/;
  var match = regex.exec(key);
  var keyNum;
  if(match) {
    key = (parseInt(match[1],17) - 5) % 7;
    key *=2 ;
    if(key > 5) key--;
    var sharpFlat = true;
    switch(match[2]) {
      case 'es':
        sharpFlat = false;
        --key;
        break;
      case 'is':
        ++key;
        break;
    }
    var inc = sharpFlat? 5 : 7;
    var count = 0;
    var register = key;
    while(count == 0) {
      while(count <= 7 && register % 12 != 0) {
        register += inc;
        count++;
      }
      if(count <= 7) break;    
      sharpFlat = !sharpFlat;
      inc = 12 - inc;
      register = key;
      count = 0;
    }
    selSharpsFlats = sharpFlat;
    keyNum = count;
  } else {
    keyNum = 0;
  }
  $('#txtKeyNum').val(keyNum);
  updateSharpsFlatsText();
}
var keyToNum = function(key){
  var regex = /^([a-gA-G])([ei]s)?([',]*)$/;
  var match = regex.exec(key);
  if(match) {
    key = (parseInt(match[1],17) - 5) % 7;
    key *=2 ;
    if(key > 5) key--;
    switch(match[2]) {
      case 'es':
        --key;
        break;
      case 'is':
        ++key;
        break;
    }
    for(var i=match[3].length-1; i>=0; --i){
      key += (match[3][i]==',')? -12 : 12;
    }
  } else {
    key = 0;
  }
  return key;
};
var numToKey = function(pitch,favorSharps){
  pitch %= 12;
  while(pitch < 0) {
    pitch = pitch + 12;
  }
  if(pitch >= 5) {
    pitch++;
  }
  var key = (Math.floor(pitch / 2) + 2) % 7;  // +2 mod 7 to shift c from 0 to 2.
  var sharp = (pitch%2)==1;
  if(!sharp) {
    key = (key+10).toString(17);
  } else if(favorSharps) {
    key = (key+10).toString(17) + 'is';
  } else {
    key = (key + 1)%7;
    key = (key+10).toString(17) + 'es';
  }
  return key;
};
var updateKeySig = function(){
  var sign = selSharpsFlats? 1 : -1;
  var pitch = (sign * 7 * $('#txtKeyNum').val()) % 12;
  selKey = numToKey(pitch, selSharpsFlats);
  $('._key').val(selKey);
  updateTransposeKey();
};
var updateTransposeKey = function(){
  if(selTransposeNum == 0) {
    selTransposeKey = selKey;
  } else {
    var keyNum = keyToNum(selKey);
    keyNum += selTransposeNum;
    key = numToKey(keyNum);
    var octave = Math.floor(keyNum/12);
    key += ((octave > 0)? "'" : ",").repeat(Math.abs(octave));
    selTransposeKey = key;
  }
  $('._transposekey').val(selTransposeKey);
  console.info(selTransposeKey);
};
var ptsettings = ["*2", "*3/8", "s8", function (match,first,duration,second,last){
                        if(second)duration /= 2;
                        else second = "";
                        return first + '*3/' + (8/duration) + second + last;
                      }];
function partBlurred(e) {
  if(selTemplate=='choral-tone'){
    var $this = $(this),
        txt = $this.val();
    txt = txt.replace(/(\\leftBracket\s[^a-grs]*[a-g](?:is|es)?2)(?:\*\d+(?:\/\d+)?)?([^a-g]*(?:\\[a-z]+\s*)*\\divisioMaior)/gi,'$1'+ptsettings[0]+'$2');
    txt = txt.replace(/(\\recit\s[^a-grs]*[a-g](?:is|es)?1)(?:\*\d+(?:\/\d+)?)?([^a-g]*(?:\\[a-z]+\s*)*\\rightBracket)/gi,'$1'+ptsettings[1]+'$2');
    txt = txt.replace(/(\\divisioMaxima)(?:\s*\\mediant)?(\s+)(s\d+(?:\*\d+(?:\/\d+)?)?)?\s*(\s)/g,'$1 '+ptsettings[2] + '$4');
    txt = txt.replace(/([a-g](?:is|es)?[,']*([124]))(?:\*\d+(?:\/\d+)?)?(\(?\s*[a-g](?:is|es)?\)?)?(\s*(?:\\[a-z]+\s*)*\\(?:divisioMaxima|finalis))/gi,
                      ptsettings[3]);
    $this.val(txt);
  }
}
function toggleEditorVisiblity(e) {
  var visible = $('#editor').toggle().is(':visible');
  $('#lnkToggleEditor').html((visible?'–':'+') + 'Editor');
  windowResized();
  if(e && e.preventDefault) e.preventDefault();
}
function setLyTuneAutocomplete() {
  var dir = 'hymn-tunes';
  if(selLayout == 'satb' && selTemplate == 'hymn') {
    dir = 'hymn-harmonizations';
  }
  $('#lyTune').autocomplete({
    source: '../ac.php?root=engravings/modern/' + dir + '/&extension=json',
    select: function(e,ui) {
      var dir = 'hymn-tunes';
      if(selLayout == 'satb' && selTemplate == 'hymn') {
        dir = 'hymn-harmonizations';
      }
      $($("#lyTune").prop('labels')).find('a').attr('href', '#modern/' + dir + '/' + ui.item.value)
        .text(dir == 'hymn-tunes'? 'Tune' : 'Music');
    },
    minLength: 0
  });
}
$(function() {
  $.ajaxSetup({cache:false});
  $("#cbCrop").button({icons:{primary: "ui-icon-check"}}).change(cropChanged);
  $("#cbHideTextLeft").button().change(hideTextLeftChanged);
  $("#btnType,#btnTemplate,#btnSpacing,#btnWidth,#btnHeight,#btnLayout,#btnKey,#btnTranspose").button({create:windowResized});
  $("#radioType,#radioTemplate,#radioSpacing,#radioWidth,#radioHeight,#radioLayout").buttonsetv({widthFunc:function(){return $('#'+this.id.replace(/^radio/,'lbl')).width();}});
  $("#lySuppressStems,#lySuppressTimeSignature").button().change(function(){
    $(this).button({icons:this.checked?{primary: "ui-icon-check"}:{}});
  });
  $('#lySop,#lyAlt,#lyTen,#lyBas').blur(partBlurred);
  var selectAll = function(e){
    e.preventDefault();
    this.selectionStart = 0;
    this.selectionEnd = 1;
  }
  $('#txtKeyNum').focusin(selectAll).select(selectAll).keyup(txtKeyUp);
  $('#txtTranspose').focusin(selectAll).keyup(txtTransposeKeyUp).keydown(txtTransposeKeyDown);
  $('#btnSharpsFlats').click(function(e){
    e.preventDefault();
    selSharpsFlats = !selSharpsFlats;
    updateSharpsFlatsText();
  }).click();
  $('#btnTransposeUpDown').click(function(e){
    e.preventDefault();
    selTransposeUpDown = !selTransposeUpDown;
    updateTransposeUpDownText();
    $('#txtTranspose').focus();
  }).click();
  $('#btnKey').click(function(e){
    $('#txtKeyNum').focus();
  });
  $('#btnTranspose').click(function(e){
    $('#txtTranspose').focus();
  });
  $("#chant-parent2").resizable({handles:"e"});
  if(location.protocol.slice(0,4) != "http" ||
     !location.hostname.match(/(?:www\.)?(?:illuminarepublications|sacredmusicproject)\.com/i)
    ) {
    processUrl = "http://www.illuminarepublications.com/dev/process.php";
    $("#imageForm,#pdfForm").attr("action",processUrl);
  }
  
  $(window).resize(windowResized);
  $("#lnkPreview").click(callImage);
  $("#lnkPDF").click(callPdf);
  $("#lnkSave").click(callSave);
  $("#lnkPlayScore").click(function(e){playScore(true);e.preventDefault();});
  $('#lnkToggleEditor').click(toggleEditorVisiblity);
  $("#lnkClearFields").click(clearFields);
  $("#txtWidth").keyup(widthChanged).focus(function(){
    $('#rbWidthCustom').prop('checked',true);
  });
  $("#txtHeight").keyup(heightChanged).focus(function(){
    $('#rbHeightCustom').prop('checked',true);
  });;
  $("#btnType,#btnTemplate,#btnSpacing,#btnWidth,#btnHeight,#btnLayout,#lblType,#lblTemplate,#lblSpacing,#lblWidth,#lblHeight,#lblLayout").mouseenter(showRadio).mouseleave(hideRadio).change(overrideChanged);
  $("#radioType,#radioTemplate,#radioSpacing,#radioWidth,#radioHeight,#radioLayout").mouseenter(dontAllowHide).mouseleave(allowHide);
  $("input[name=rbType]").change(typeChanged);
  $("input[name=rbTemplate]").change(templateChanged);
  $("input[name=rbSpacing]").change(spacingChanged);
  $("input[name=rbWidth]").change(widthChanged);
  $("input[name=rbHeight]").change(heightChanged);
  $("input[name=rbLayout]").change(layoutChanged);
  $("#rbWidthCustom").change(function(){if(this.checked)$("#txtWidth").select();});
  $("#rbHeightCustom").change(function(){if(this.checked)$("#txtHeight").select();});
  $('#toggleRefrainPosition').click(function(e){e.preventDefault(); $(this).text((selRefrainTop = !selRefrainTop)? 'Beginning' : 'End');});
  
  $("textarea.autosize").autosize();
  
  $('.lyOnly,.gabcOnly').show();
  $('a[remove]').click(removeClick);
  $('#setInitialCaps').click(setInitialCaps);
  var extension = (engravingType=='modern'?'json':'gabc');
  $('#txtLoad').click(function(){$(this).autocomplete('search');}).autocomplete({
    source: "../ac.php?root=engravings/"+engravingType+"/&extension="+extension,
    select: loadSelect,
    minLength: 0
  });
  
  $('#txtLoadText').click(function(){$(this).autocomplete('search');}).autocomplete({
    source: "../ac.php?root=texts/&extension=txt",
    select: loadSelectText,
    minLength: 0
  });
  $('#lyDir').autocomplete({
    source: '../ac.php?root=engravings/modern/&extension=/',
    minLength: 0
  });
  $('#lyText').change(function(e){
    $($(this).prop('labels')).find('a').attr('href', '../texts.php#hymn-texts/' + $(this).val());
  }).autocomplete({
    source: '../ac.php?root=hymn-texts/&extension=json',
    select: function(e,ui) {
      $($("#lyText").prop('labels')).find('a').attr('href', '../texts.php#hymn-texts/' + ui.item.value);
    },
    minLength: 0
  });
  var dir = 'hymn-tunes';
  if(selLayout == 'satb' && selTemplate == 'hymn') {
    dir = 'hymn-harmonizations';
  }
  $('#lyTune').change(function(e){
    var dir = 'hymn-tunes';
    if(selLayout == 'satb' && selTemplate == 'hymn') {
      dir = 'hymn-harmonizations';
    }
    $($(this).prop('labels')).find('a').attr('href', '#modern/' + dir + '/' + $(this).val())
      .text(dir == 'hymn-tunes'? 'Tune' : 'Music');
    windowResized();
  }).autocomplete({
    source: '../ac.php?root=engravings/modern/' + dir + '/&extension=json',
    select: function(e,ui) {
      var dir = 'hymn-tunes';
      if(selLayout == 'satb' && selTemplate == 'hymn') {
        dir = 'hymn-harmonizations';
      }
      $($("#lyTune").prop('labels')).find('a').attr('href', '#modern/' + dir + '/' + ui.item.value)
        .text(dir == 'hymn-tunes'? 'Tune' : 'Music');
    },
    minLength: 0
  });
  clearFields();
  spacingChanged(selSpacing,true);
  widthChanged(selWidth,true);
  heightChanged(selHeight,true);
  $(document).keydown(docKeyDown);
  setPdfLinkSelector("#lnkGabc");
  setGabcLinkSelector("#lnkDownloadSource");
  $("#editor").keyup(updateBoth).keydown(gabcEditorKeyDown).focus();
  $("#chant-image").hide().click(hideImage);
  $("#overlay").click(hideImage);
  setTimeout(function(){$("#chant-image-iframe").load(lightboxImage)},1000);
  setTimeout(windowResized,50);
  $('.lyOnly').hide();
  var regex = /(modern|square)\/(.+)$/;
  var match = regex.exec(location.hash.slice(1));
  if(match) {
    typeChanged(match[1]);
    $('#txtLoad').val(match[2]);
    load(match[2]);
  }
});


//TODO: somewhere start converting LY to ABC and rendering it with something like:
// ABCJS.renderAbc('lyPreview','%%scale 0.8\n%%staffwidth 624\nabc',null,{scale:0.5,staffwidth:624,paddingleft:0,paddingright:0,paddingtop:0});